/**
 * Program   :   DataBeanDetector.java
 * Author    :   shadow guo
 * Create    :   2013-6-5 上午11:55:42
 *
 * Copyright 2008 by Tongfu Information Technology Co. Ltd
 * All rights reserved.
 *
 * This software is the confidential and proprietary information
 * of Tongfu Information Technology Co. Ltd. ("Confidential Information").  You
 * shall not disclose such Confidential Information and shall use
 * it only in accordance with the terms of the license agreement
 * you entered into with Tongfu Information Technology Co. Ltd.
 * 
 */
package com.tongfusoft.web.utils;

import java.io.File;
import java.io.IOException;
import java.net.URI;
import java.net.URL;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.ResourceBundle;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;

import org.apache.commons.lang3.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/**
 * 根据规则获取所有的dataBean对象定义
 * 
 * @author Shadow
 * 
 */
public class DataBeanDetector {
	/**
	 * Logger for this class
	 */
	private static final Log logger = LogFactory.getLog(DataBeanDetector.class);

	private static Map<String, String> DATABEANS = new HashMap<String, String>();

	static {
		detectorClassPath();
	}

	public static String getDataBeanName(String name) {
		if (DATABEANS.containsKey(name)) {
			return DATABEANS.get(name);
		} else {
			return null;
		}
	}

	private static void detectorClassPath() {
		try {
			final Enumeration<URL> systemResources = ClassLoader
					.getSystemResources("");
			List<URL> urls = new ArrayList<URL>();

			while (systemResources.hasMoreElements()) {
				urls.add(systemResources.nextElement());
			}

			if (urls.size() == 0) {
				urls.add(Thread.currentThread().getContextClassLoader()
						.getResource(""));
			}

			for (URL url : urls) {
				logger.debug(url);
				File file = new File(url.getPath());
				discoverResources(file, file);
			}

			detectorJar();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	private static void detectorJar() {
		try{
			ResourceBundle res = ResourceBundle.getBundle("beanDetector");
			if (res != null && StringUtils.isNotEmpty(res.getString("className"))) {
				String[] classNames = StringUtils.split(res.getString("className"),
						",");
				for (int i = 0; i < classNames.length; i++) {
					try {
						String classResourceName = classNames[i].replace(".", "/")
								+ ".class";
						URL classResourceURL = DataBeanDetector.class
								.getClassLoader().getResource(classResourceName);
						String classResourcePath = classResourceURL.getPath();
	
						if (classResourceURL.getProtocol().equals("jar")) {
							if (logger.isDebugEnabled()) {
								logger.debug(classResourcePath);
							}
	
							String jarPath = classResourcePath.substring(
									classResourcePath.indexOf("/"),
									classResourceURL.getPath().indexOf("!"));
	
							JarFile jarFile = new JarFile(URLDecoder.decode(
									jarPath, "UTF-8"));
							Enumeration<JarEntry> jarEntries = jarFile.entries();
							
							while (jarEntries.hasMoreElements()) {
								JarEntry jarEntry = jarEntries.nextElement();
								String resourceName = jarEntry.getName();
								
								
								resourceName = StringUtils.replace(resourceName, "/",".");
								if(StringUtils.endsWith(resourceName, ".class")){
									resourceName = resourceName.substring(0, resourceName.length()-6);
								}
								
								try{
									if(isDataBean(Class.forName(resourceName))){
										if(logger.isDebugEnabled()){
											logger.debug(resourceName);
										}
										DATABEANS.put(getKeyName(resourceName), resourceName);
									}
								}catch(Exception e){
									logger.error(e);
								}
								
							}
						}
	
					} catch (Exception e) {
						logger.error(e);
					}
	
				}
			}
		} catch (Exception e) {
			logger.error(e);
		}
	}

	private static void discoverResources(File root, File folder) {
		if (folder.listFiles() != null)
			for (File file : folder.listFiles()) {
				if (file.isDirectory()) {
					discoverResources(root, file);
				} else {
					if (file.getName().endsWith(".class")) {
						String name = resolvePath(root, file.getParentFile())
								+ file.getName().substring(0,
										file.getName().length() - 6);
						name = StringUtils.replace(name, "/", ".");
						if (name.indexOf(".data.") > 0) {
							try {
								if (isDataBean(Class.forName(name))) {
									if(logger.isDebugEnabled()){
										logger.debug(name);
									}
									DATABEANS.put(getKeyName(name), name);
								}
							} catch (ClassNotFoundException e) {
								e.printStackTrace();
							}
						}
					}
				}
			}
	}

	private static String getKeyName(String name) {
		String[] names = StringUtils.split(name, ".");
		if (names.length > 2) {
			return names[names.length - 2] + "." + names[names.length - 1];
		} else {
			return name;
		}

	}

	private static boolean isDataBean(Class cls) {
		Class supClass = cls.getSuperclass();

		if (StringUtils.equals(supClass.getName(),
				"com.tongfusoft.web.core.data.BaseData")) {
			return true;
		} else {
			if (StringUtils.equals(supClass.getName(), "java.lang.Object")) {
				return false;
			} else {
				return isDataBean(supClass);
			}
		}

	}

	private static String resolvePath(File root, File file) {
		URI uri = root.toURI();
		URI uri2 = file.toURI();
		return uri.relativize(uri2).getPath();
	}

}
